<template>
  <div class="image-box">
    <el-skeleton style="width: 305px; text-align: center" :loading="isLoading" animated>
      <template #template>
        <el-skeleton-item variant="h3" style="width: 90%" />
        <el-skeleton-item variant="image" style="width: 263px; height: 180px; margin-left: 20px" />
        <div style="padding: 10px">
          <el-skeleton-item variant="h3" style="width: 80%" />
          <div
            style="
              display: flex;
              align-items: center;
              justify-items: space-between;
              margin-top: 16px;
              height: 16px;
            "
          >
            <el-skeleton-item variant="text" style="margin-right: 16px" />
            <el-skeleton-item variant="text" style="width: 80%" />
          </div>
          <el-skeleton-item variant="h3" style="width: 90%; margin-top: 5px" />
          <el-skeleton-item variant="h3" style="width: 90%" />
        </div>
      </template>
      <template #default>
        <el-card class="box-card" shadow="always" style="height: 100%; padding-bottom: 0">
          <template #header>
            <div class="card-header">
              <span style="margin-left: 20px">{{ imageData.category }}</span>
              <el-tag type="primary" style="float: right; margin-right: 10px">{{ imageData.sequence }}</el-tag>
            </div>
          </template>
          <el-image
            :src="imageSrc"
            :zoom-rate="1.2"
            :max-scale="7"
            :min-scale="0.2"
            :preview-src-list="[previewImageSrc]"
            :initial-index="0"
            fit="cover"
            style="width: 100%; height: 180px"
          >
            <template #error>
              <div class="image-slot">
                <el-icon><Picture></Picture></el-icon>
              </div>
            </template>
          </el-image>
          <div style="display: flex; justify-content: center">
            <span style="display: inline-block">{{ imageData.name }}</span>
          </div>
          <div style="display: flex; justify-content: center; margin-top: 5px">
            <el-button type="success" size="small" @click="imageDetailShow = true">更多</el-button>
          </div>

          <template #footer>
            <div v-if="!loadTagFailed">
              <div v-if="noTagData" style="display: flex; justify-content: center">
                <el-text class="mx-1" type="info">无标签</el-text>
              </div>
              <div v-else class="tag-box">
                <el-tooltip
                  v-for="tag in tagData"
                  :key="tag.id"
                  effect="dark"
                  :content="tag.isCategory ? '此标签属于数据集' : '此标签属于图片'"
                  placement="bottom"
                >
                  <el-tag
                    effect="dark"
                    :type="tag.isCategory ? 'warning' : 'success'"
                    style="margin-right: 10px; cursor: default"
                    round
                  >
                    {{ tag.content }}
                  </el-tag>
                </el-tooltip>
              </div>
            </div>
            <div v-else style="display: flex; justify-content: center">
              <el-text class="mx-1" type="danger">加载标签失败</el-text>
            </div>
          </template>
        </el-card>
      </template>
    </el-skeleton>

    <!-- 图片详细信息 -->
    <el-dialog v-model="imageDetailShow" title="图片详细信息" width="800" destroy-on-close center>
      <div class="image-detail">
        <span style="display: block; font-size: larger; width: 100%"><el-text class="mx-1" type="primary">数据集: </el-text>{{ imageData.category }}</span>
        <span style="display: block; font-size: larger; width: 100%"><el-text class="mx-1" type="primary">名称: </el-text>{{ imageData.name }}</span>
        <div style="width: 100%; display: flex; justify-content: center">
          <el-image
            :src="previewImageSrc"
            :zoom-rate="1.2"
            :max-scale="7"
            :min-scale="0.2"
            :preview-src-list="[previewImageSrc]"
            :initial-index="0"
            fit="cover"
            style="display: block; width: 60%; height: 100%"
          >
            <template #error>
              <div class="image-slot">
                <el-icon><Picture></Picture></el-icon>
              </div>
            </template>
          </el-image>
        </div>

        <div v-if="noTagData" style="display: flex; justify-content: center">
          <el-text class="mx-1" type="info">无标签</el-text>
        </div>

        <el-tooltip
          v-else
          v-for="tag in tagData"
          :key="tag.id"
          effect="dark"
          :content="tag.isCategory ? '此标签属于数据集' : '此标签属于图片'"
          placement="bottom"
        >
          <el-tag
            effect="dark"
            :type="tag.isCategory ? 'warning' : 'success'"
            style="margin-right: 10px; cursor: default; margin-top: 10px"
            round
          >
            {{ tag.content }}
          </el-tag>
        </el-tooltip>
        <span v-if="hasPerm('ROLE_admin')" style="display: block; width: 100%; font-size: large">
          <el-text class="mx-1" type="primary">ID:</el-text>
          {{ imageData.id }}
        </span>
        <span style="display: block; width: 100%; font-size: large">
          <el-text class="mx-1" type="primary">介绍:</el-text>
          {{ imageInfo }}
        </span>
        <!-- 图片操作 -->
        <div class="options-box">
          <el-button type="primary" plain :icon="Download" @click="downloadImage" size="small">下载</el-button>
        </div>

        <div v-if="hasPerm('tag_stick')" class="options-box">
          <el-text class="mx-1" type="primary" style="user-select: none">编辑标签:</el-text>
          <el-cascader
            collapse-tags
            v-model="selectedTags"
            :props="selectorProps"
            placeholder="选择操作"
            clearable
            :key="resetCascader"
          ></el-cascader>
          <el-button
            type="primary"
            plain
            @click="openConfirmBox('确认执行吗', tagManageHandle)"
            style="border-radius: 0 5px 5px 0"
          >
            执行
          </el-button>
        </div>
        <div v-if="hasPerm('image_cd')">
          <el-button type="danger" plain @click="openConfirmBox('确认删除图片?(无法恢复)', deleteImage)">
            删除图片
          </el-button>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="imageDetailShow = false">关闭</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { onBeforeMount, ref } from "vue"
import {
  getOriginImageApi,
  getSimpleImageApi,
  getImageDescription,
  deleteImageApi
} from "@/api/data-manager/imageApi"
import { getAllTagApi, getImageTagsApi, addTagToImageApi, deleteTagFromImageApi } from "@/api/data-manager/tagApi"
import { Picture, Download } from "@element-plus/icons-vue"
import { useLoginStore } from "@/store/loginStore.ts"
import { CascaderProps, ElMessage } from "element-plus"
import { openConfirmBox } from "@/utils/confirmBox.ts"

const emit = defineEmits(["delete-image"])

const loginStore = useLoginStore()

const isLoading = ref<boolean>(true)
const isFailed = ref<boolean>(false)

const loadTagFailed = ref<boolean>(false)

const tagData = ref<any[]>()
const noTagData = ref<boolean>(false)

const props = defineProps(["imageData"])
const rawImageId = ref<any>(props.imageData.id)

const imageData = ref(props.imageData)

const imageSrc = ref()
const previewImageSrc = ref()

const imageDetailShow = ref<boolean>(false)
const imageInfo = ref<string>()

const selectedTags = ref<number[]>()

const resetCascader = ref<number>(1)
//标签管理选择器配置
const selectorProps: CascaderProps = {
  lazy: true,
  multiple: true,
  lazyLoad(node, resolve) {
    const { level } = node
    setTimeout(async () => {
      if (level === 0) {
        resolve([
          {
            value: "add",
            label: "添加",
            leaf: false
          },
          {
            value: "remove",
            label: "删除",
            leaf: false
          }
        ])
      } else {
        const tagsId = tagData.value ? tagData.value!.map((tag) => tag.id) : []
        
        let res
        try {
          res = await getAllTagApi()
        } catch (error) {
          ElMessage.error("获取标签失败")
          return
        }
        const tags: any[] = res.data
        
        if (node.value === "add") {
          resolve(
            tags
              .filter((tag) => !tagsId.includes(tag.id))
              .map((tag) => ({
                value: tag.id,
                label: tag.content,
                leaf: true
              }))
          )
        } else {
          resolve(
            tags
              .filter((tag) => tagsId.includes(tag.id))
              .map((tag) => ({
                value: tag.id,
                label: tag.content,
                leaf: true
              }))
          )
        }
      }
    })
  }
}

//进行标签增删操作
function tagManageHandle() {
  if (selectedTags.value?.length == 0) {
    ElMessage.warning("请选择数据")
    return
  }

  let removeTags: number[] = []
  let addTags: number[] = []

  selectedTags.value?.forEach((tag: any) => {
    tag[0] === "add" ? addTags.push(tag[1]) : removeTags.push(tag[1])
  })

  setTimeout(async () => {
    if (removeTags.length > 0) {
      await deleteTagFromImageApi(imageData.value.id, removeTags)
    }

    if (addTags.length > 0) {
      await addTagToImageApi(imageData.value.id, addTags)
    }
    await getTags()
    resetCascader.value = resetCascader.value % 2 == 0 ? 1 : 2
    selectedTags.value = []
    ElMessage.success("操作成功" + tagData.value?.length)
  })
}

//删除图片操作
function deleteImage() {
  setTimeout(async () => {
    await deleteImageApi(imageData.value.id)
    imageDetailShow.value = false
    ElMessage.success("操作成功")
    emit("delete-image")
  })
}

//初始化
onBeforeMount(async () => {
  setTimeout(async () => {
    previewImageSrc.value = await getOriginImageApi(rawImageId.value)
  })

  setTimeout(async () => {
    let res
    try {
      res = await getImageDescription(rawImageId.value)
    } catch (error) {
      imageInfo.value = "获取图片描述失败"
      return
    }
    imageInfo.value = res.data
  })

  setTimeout(async () => {
    let data
    try {
      data = await getSimpleImageApi(rawImageId.value)
    } catch (error) {
      isFailed.value = true
      isLoading.value = false
      return
    }
    imageSrc.value = data
    isLoading.value = false
  })
  getTags()
})

async function getTags() {
  let res
  try {
    res = await getImageTagsApi(rawImageId.value)
  } catch (error) {
    loadTagFailed.value = true
    return
  }
  if (res.data && res.data.length > 0) {
    noTagData.value = false
  } else {
    noTagData.value = true
  }
  tagData.value = res.data
}

//下载图片
function downloadImage() {
  const a = document.createElement("a")
  const event = new MouseEvent("click")
  a.download = imageData.value.name + ".jpg"
  a.href = previewImageSrc.value
  a.dispatchEvent(event)
}

//权限检测
function hasPerm(perm: string) {
  return loginStore.perms.includes(perm)
}
</script>

<style lang="scss" scoped>
.image-box {
  width: 305px;
  margin: 20px;
  height: 90%;

  :deep(.el-image__preview) {
    cursor: zoom-in;
  }

  :deep(.el-card__body) {
    padding-bottom: 10px;
  }
  .image-detail {
    display: flex;
    justify-content: center;
    text-align: center;
    flex-wrap: wrap;
  }

  .options-box {
    width: 100%;
    margin: 5px;
  }
}
.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: var(--el-fill-color-light);
  color: var(--el-text-color-secondary);
  font-size: 30px;
}
</style>
